﻿@page "/structuredlogs"
@page "/structuredlogs/resource/{resourceName}"

@using Aspire.Dashboard.Otlp.Model
@using Aspire.Dashboard.Utils
@using Aspire.Dashboard.Resources
@using System.Globalization
@using Aspire.Dashboard.Components.Controls.Grid
@using Aspire.Dashboard.Model
@inject IJSRuntime JS
@implements IDisposable

@inject IStringLocalizer<Dashboard.Resources.StructuredLogs> Loc
@inject IStringLocalizer<ControlsStrings> ControlsStringsLoc
@inject IStringLocalizer<StructuredFiltering> FilterLoc
@inject IStringLocalizer<Dialogs> DialogsLoc

<PageTitle>
    <ApplicationName
        AdditionalText="@PageViewModel.SelectedResource.Id?.ReplicaSetName"
        ResourceName="@nameof(Dashboard.Resources.StructuredLogs.StructuredLogsPageTitle)"
        Loc="@Loc"/>
</PageTitle>

<div class="page-content-container">
    <AspirePageContentLayout @ref="@_contentLayout"
                             AddNewlineOnToolbar="true"
                             IsSummaryDetailsViewOpen="@(SelectedLogEntry is not null)">
        <PageTitleSection>
            <h1 class="page-header">@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsHeader)]</h1>
        </PageTitleSection>
        <ToolbarSection>
            <ResourceSelect Resources="_resourceViewModels"
                            AriaLabel="@ControlsStringsLoc[nameof(ControlsStrings.SelectAResource)]"
                            @bind-SelectedResource="PageViewModel.SelectedResource"
                            @bind-SelectedResource:after="HandleSelectedResourceChangedAsync"
                            CanSelectGrouping="true"
                            LabelClass="toolbar-left" />

            <SignalsActionsDisplay HandleClearSignal="@ClearStructureLogs"
                                  IsPaused="@PauseManager.AreStructuredLogsPaused(out _)"
                                  OnPausedChanged="@PauseManager.SetStructuredLogsPaused"
                                  SelectedResource="@PageViewModel.SelectedResource" />

            <FluentSearch @bind-Value="_filter"
                          @bind-Value:after="HandleAfterFilterBindAsync"
                          Immediate="true"
                          ImmediateDelay="@FluentUIExtensions.InputDelay"
                          Placeholder="@ControlsStringsLoc[nameof(ControlsStrings.FilterPlaceholder)]"
                          title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsMessageFilter)]"
                          slot="end" />

            <DesktopToolbarDivider />

            <LogLevelSelect slot="end"
                            @bind-LogLevel="@PageViewModel.SelectedLogLevel"
                            LogLevels="@_logLevels"
                            HandleSelectedLogLevelChangedAsync="@HandleSelectedLogLevelChangedAsync" />

            <DesktopToolbarDivider />

            @if (ViewModel.Filters.Count == 0)
            {
                if (ViewportInformation.IsDesktop)
                {
                    <span slot="end">@FilterLoc[nameof(StructuredFiltering.NoFilters)]</span>
                }
            }
            else
            {
                <div slot="end">
                    <FluentCounterBadge HorizontalPosition="70" Count="@(ViewModel.Filters.GetEnabledFilters().Count())" Appearance="Appearance.Accent">
                        <AspireMenuButton HideIcon="true" Text="@FilterLoc[nameof(StructuredFiltering.Filters)]" Items="@GetFilterMenuItems()" />
                    </FluentCounterBadge>
                </div>
            }

            <DesktopToolbarDivider />

            <FluentButton slot="end" Appearance="Appearance.Stealth"
                          aria-label="@FilterLoc[nameof(StructuredFiltering.AddFilter)]"
                          OnClick="() => OpenFilterAsync(null)">
                @if (ViewportInformation.IsDesktop)
                {
                    <FluentIcon Value="@(new Icons.Regular.Size20.Filter())"/>
                }
                else
                {
                    <FluentIcon Class="align-text-bottom" Value="@(new Icons.Regular.Size20.Filter())"/>
                    @FilterLoc[nameof(StructuredFiltering.AddFilter)]
                }
            </FluentButton>
        </ToolbarSection>

        <MainSection>
            <SummaryDetailsView
                ShowDetails="@(SelectedLogEntry is not null)"
                OnDismiss="@(() => ClearSelectedLogEntryAsync(causedByUserAction: true))"
                ViewKey="StructuredLogsList"
                SelectedValue="@SelectedLogEntry"
                OnResize="@(r => _manager.SetWidthFraction(r.Orientation == Orientation.Horizontal ? r.Panel1Fraction : 1))">
                <DetailsTitleTemplate>
                    @{
                        var eventName = StructureLogsDetailsViewModel.GetEventName(context!.LogEntry, Loc);
                    }

                    <div class="pane-details-title" title="@($"{eventName} ({context!.LogEntry.Scope.Name})")">
                        @eventName
                        <span class="pane-details-subtext">@context!.LogEntry.Scope.Name</span>
                    </div>
                </DetailsTitleTemplate>
                <Summary>
                    <div class="logs-summary-layout">
                        <div class="logs-grid-container continuous-scroll-overflow">
                            <GridColumnManager @ref="_manager" Columns="@_gridColumns">
                                <FluentDataGrid @ref="_dataGrid"
                                                ColumnResizeLabels="@_resizeLabels"
                                                ColumnSortLabels="@_sortLabels"
                                                HeaderCellAsButtonWithMenu="true"
                                                ResizeType="DataGridResizeType.Discrete"
                                                Virtualize="true"
                                                RowClass="@GetRowClass"
                                                GenerateHeader="GenerateHeaderOption.Sticky"
                                                ItemSize="46"
                                                OverscanCount="100"
                                                ResizableColumns="true"
                                                ResizeColumnOnAllRows="false"
                                                ItemsProvider="@GetData"
                                                TGridItem="OtlpLogEntry"
                                                GridTemplateColumns="@_manager.GetGridTemplateColumns()"
                                                ShowHover="true"
                                                ItemKey="@(r => r.InternalId)"
                                                OnRowClick="@(r => r.ExecuteOnDefault(d => OnShowPropertiesAsync(d, buttonId: null)))"
                                                Class="main-grid enable-row-click">
                                    <ChildContent>
                                        <AspireTemplateColumn ColumnId="@ResourceColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsResourceColumnHeader)]" Tooltip="true" TooltipText="@(e => GetResourceName(e.ResourceView))">
                                            <span style="padding-left:5px; border-left-width: 5px; border-left-style: solid; border-left-color: @(ColorGenerator.Instance.GetColorHexByKey(GetResourceName(context.ResourceView)));">
                                                @GetResourceName(context.ResourceView)
                                            </span>
                                        </AspireTemplateColumn>
                                        <AspireTemplateColumn ColumnId="@LogLevelColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsLevelColumnHeader)]">
                                            <LogLevelColumnDisplay LogEntry="@context" />
                                        </AspireTemplateColumn>
                                        <AspireTemplateColumn ColumnId="@TimestampColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsTimestampColumnHeader)]" TooltipText="@(context => FormatHelpers.FormatDateTime(TimeProvider, context.TimeStamp, MillisecondsDisplay.Full, CultureInfo.CurrentCulture))" Tooltip="true">
                                            @FormatHelpers.FormatTimeWithOptionalDate(TimeProvider, context.TimeStamp, MillisecondsDisplay.Truncated)
                                        </AspireTemplateColumn>
                                        <AspireTemplateColumn ColumnId="@MessageColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsMessageColumnHeader)]">
                                            @* Tooltip is displayed by the message GridValue instance *@
                                            <LogMessageColumnDisplay FilterText="@(ViewModel.FilterText)" LogEntry="@context" />
                                        </AspireTemplateColumn>
                                        <AspireTemplateColumn ColumnId="@TraceColumn" ColumnManager="@_manager" Title="@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsTraceColumnHeader)]">
                                            @if (!string.IsNullOrEmpty(context.TraceId))
                                            {
                                                <a href="@DashboardUrls.TraceDetailUrl(context.TraceId, context.SpanId)" class="long-inner-content" @onclick:stopPropagation="true">
                                                    @OtlpHelpers.ToShortenedId(context.TraceId)
                                                </a>
                                            }
                                            else
                                            {
                                                <span class="empty-data"></span>
                                            }
                                        </AspireTemplateColumn>
                                        <AspireTemplateColumn ColumnId="@ActionsColumn" ColumnManager="@_manager" Title="@ControlsStringsLoc[nameof(ControlsStrings.ActionsColumnHeader)]" Class="no-ellipsis">
                                            @{
                                                var id = $"details-button-{context.InternalId}";
                                            }
                                            <div class="grid-action-container" @onclick:stopPropagation="true">
                                                <StructuredLogActions LogEntry="@context"
                                                                      OnViewDetails="@((buttonId) => OnShowPropertiesAsync(context, buttonId))" />
                                            </div>
                                        </AspireTemplateColumn>
                                    </ChildContent>
                                    <EmptyContent>
                                        <FluentIcon Icon="Icons.Regular.Size24.SlideTextSparkle" />&nbsp;@Loc[nameof(Dashboard.Resources.StructuredLogs.StructuredLogsNoLogsFound)]
                                    </EmptyContent>
                                </FluentDataGrid>
                            </GridColumnManager>
                        </div>
                    </div>
                </Summary>
                <Details>
                    <StructuredLogDetails ViewModel="context" />
                </Details>
            </SummaryDetailsView>
        </MainSection>
        <FooterSection>
            <TotalItemsFooter @ref="_totalItemsFooter"
                              TotalItemCount="@_totalItemsCount"
                              SingularText="@Loc[nameof(Dashboard.Resources.StructuredLogs.TotalItemsFooterSingularText)]"
                              PluralText="@Loc[nameof(Dashboard.Resources.StructuredLogs.TotalItemsFooterPluralText)]"
                              PauseText="@PauseText"/>
        </FooterSection>
    </AspirePageContentLayout>
</div>
